﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GameDataTempshitEditor
{
    public partial class ClassPicker : Form
    {
        public ClassPicker()
        {
            InitializeComponent();

            this.Load += ClassPicker_Load;
        }

        void ClassPicker_Load(object sender, EventArgs e)
        {
            // set location to be near the mouse button
            int x = Math.Max(0, Math.Min(Cursor.Position.X - (Width / 2), SystemInformation.VirtualScreen.Width - Width));
            int y = Math.Max(0, Math.Min(Cursor.Position.Y - (Height / 2), SystemInformation.VirtualScreen.Height - Height));
            SetDesktopLocation(x,y);
        }

        private class TreeNode_ReflectionClass : TreeNode
        {
            public readonly Red.GameData.Raw.ReflectionClass _Class;

            public TreeNode_ReflectionClass(Font font, Red.GameData.Raw.ReflectionClass cls)
                : base(cls.Name)
            {
                _Class = cls;

                // extract class flags
                if (cls.IsAbstract || cls.KeyName != "")
                {
                    FontStyle style = font.Style;
                    if (cls.IsAbstract)
                        style |= FontStyle.Italic;
                    if (cls.KeyName != "")
                        style |= FontStyle.Bold;

                    NodeFont = new Font(font, font.Style | style);
                }

                // child classes
                foreach (var childClass in cls.Children)
                    Nodes.Add(new TreeNode_ReflectionClass(font, childClass));
            }

            public TreeNode_ReflectionClass FindTreeNode(Red.GameData.Raw.ReflectionClass _class)
            {
                if (_class == _Class)
                    return this;

                foreach (TreeNode_ReflectionClass tn in Nodes)
                {
                    TreeNode_ReflectionClass ret = tn.FindTreeNode(_class);
                    if (ret != null)
                        return ret;
                }

                return null;
            }
        }

        // select a class from the class tree, returns NULL on cancel
        public Red.GameData.Raw.ReflectionClass SelectClass(Red.GameData.Raw.ReflectionClass baseClass, Red.GameData.Raw.ReflectionClass currentClass)
        {
            // only one class possible, early exit
            if (baseClass != null && baseClass.Children.Count == 0)
                return baseClass;

            // fill list of controls
            treeView1.Nodes.Clear();
            treeView1.Nodes.Add(new TreeNode_ReflectionClass(Font, baseClass));
            treeView1.ExpandAll();

            // select existing class
            var selectedNode = ((TreeNode_ReflectionClass)(treeView1.Nodes[0])).FindTreeNode(currentClass);
            treeView1.SelectedNode = selectedNode;

            // show the dialog
            if (ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
                return null;

            if (treeView1.SelectedNode == null)
                return null;

            var selectedClass = ((TreeNode_ReflectionClass)treeView1.SelectedNode)._Class;
            return selectedClass;
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            var selectedNode = e.Node as TreeNode_ReflectionClass;
            Red.GameData.Raw.ReflectionClass selectedClass = null;
            if (selectedNode != null)
            {
                selectedClass = selectedNode._Class;
            }

            buttonOK.Enabled = (selectedClass != null) && (!selectedClass.IsAbstract);
        }

        private void treeView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Point targetPoint = treeView1.PointToClient(Cursor.Position);
            var selectedNode = treeView1.GetNodeAt(targetPoint) as TreeNode_ReflectionClass;
            if (selectedNode != null)
            {
                var selectedClass = selectedNode._Class;
                if (selectedClass != null && !selectedClass.IsAbstract)
                {
                    DialogResult = System.Windows.Forms.DialogResult.OK;
                }
            }
        }

        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Action == TreeViewAction.ByMouse )
            {
                e.Cancel = true;
                return;
            }
        }

        private void treeView1_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Action == TreeViewAction.ByMouse)
            {
                e.Cancel = true;
                return;
            }
        }
    }
}
